package com.itita.ww2.game.worldmap;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.itita.ww2.core.R;
import com.itita.ww2.core.ServerService;
import com.itita.ww2.data.WorldMapConfig;
import com.itita.ww2.game.alliance.event.AllianceEventDispatch;
import com.itita.ww2.game.alliance.event.IAllianceDisbandListener;
import com.itita.ww2.game.alliance.event.IAllianceMemberRemovedListener;
import com.itita.ww2.game.enums.StateEnum;
import com.itita.ww2.model.user.UserProfile;
import com.itita.ww2.model.worldmap.Base;
import com.itita.ww2.model.worldmap.Block;
import com.itita.ww2.model.worldmap.City;
import com.itita.ww2.puredb.model.Alliance;
import com.itita.ww2.puredb.model.AllianceMember;
import com.itita.ww2.puredb.model.AllianceUserQuitCD;
import com.itita.ww2.redis.RedisUtil;
import com.itita.ww2.redis.cache.Hash;
import com.itita.ww2.redis.cache.Table;
import com.itita.ww2.redis.core.Redis;
import com.itita.ww2.utils.DataUtil;
import com.smartfoxserver.v2.db.IDBManager;
import com.smartfoxserver.v2.entities.data.ISFSArray;
import com.smartfoxserver.v2.entities.data.ISFSObject;

/**
 * 大地图数据管理
 * @author NorthLan
 *
 */
@SuppressWarnings("unused")
public class WorldMapManager {

	private static final Logger logger = LoggerFactory.getLogger(WorldMapManager.class);
	private static WorldMapManager instance = new WorldMapManager();

	public static WorldMapManager getInstance() {
		return instance;
	}

	private ConcurrentHashMap<Integer, Block> m_WorldMapData;
	//
	private Table cacheCityTable;
	private Table cacheBaseTable;
	private Hash cacheLastestBattleTable;

	private WorldMapManager() {
		m_WorldMapData = new ConcurrentHashMap<>();
	}

	public void init() {
		initData();
		initRedis();
		loadData();
		initEvent();
	}

	private void initData() {
		IDBManager dbManager = ServerService.getInstance().getSFSDBManager();
		try {
			// worldmap_city
			{
				StringBuilder sb = new StringBuilder();
				sb.append("INSERT IGNORE INTO `worldmap_city` (`cityId`,`blockId`,`type`)");
				sb.append(" VALUES ");
				ISFSArray cityData = WorldMapConfig.getAllCityList();
				for (int i = 0; i < cityData.size(); ++i) {
					ISFSObject obj = cityData.getSFSObject(i);
					sb.append("(").append(obj.getInt("id"));
					sb.append(",").append(obj.getInt("blockId"));
					sb.append(",").append(obj.getInt("type"));
					sb.append(")");
					// 末位不加 ','
					if (i != cityData.size() - 1) {
						sb.append(",");
					}
				}
				if (cityData.size() != 0) {
					dbManager.executeInsert(sb.toString(), null);
				}
			}
			// worldmap_base
			{
				StringBuilder sb = new StringBuilder();
				sb.append("INSERT IGNORE INTO `worldmap_base` (`blockId`,`cityId`,`baseId`,`level`,`mapdata`)");
				sb.append(" VALUES ");
				ISFSArray baseData = WorldMapConfig.getAllBaseList();
				for (int i = 0; i < baseData.size(); ++i) {
					ISFSObject obj = baseData.getSFSObject(i);
					int blockId = obj.getInt("blockId");
					int cityId = obj.getInt("cityId");
					int baseId = obj.getInt("id");

					sb.append("(").append(blockId);
					sb.append(",").append(cityId);
					sb.append(",").append(baseId);
					sb.append(",").append(obj.getInt("level"));
					sb.append(",").append("'").append(WorldMapConfig.getBaseMap(blockId, cityId, baseId).toJson())
							.append("'");
					sb.append(")");
					if (i != baseData.size() - 1) {
						sb.append(",");
					}
				}
				if (baseData.size() != 0) {
					dbManager.executeInsert(sb.toString(), null);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	private void initRedis() {
		Redis redis = ServerService.getInstance().getRedis();
		// 
		cacheCityTable = redis
				.setTable(R.ServerRedisKey.NAME_WORLDMAP_CITY, RedisUtil.genericKey("blockId", "cityId"), false, true)
				.init();
		cacheBaseTable = redis.setTable(R.ServerRedisKey.NAME_WORLDMAP_BASE,
				RedisUtil.genericKey("blockId", "cityId", "baseId"), false, true).init();
		cacheLastestBattleTable = redis.setHash(R.ServerRedisKey.NAME_WORLDMAP_LASTESTBATTLE).useIndexKey()
				.withMaxRow(10).withSort("time"); // 排序10条
	}

	private void loadData() {
		List<Map<String, String>> m_dataList = cacheBaseTable.getAllValue();
		for (Map<String, String> map : m_dataList) {
			int blockId = DataUtil.intValueOf(map.get("blockId"));
			int cityId = DataUtil.intValueOf(map.get("cityId"));
			int baseId = DataUtil.intValueOf(map.get("baseId"));
			// block
			if (!m_WorldMapData.containsKey(blockId)) {
				m_WorldMapData.put(blockId, new Block(blockId));
			}
			// city
			Block m_block = m_WorldMapData.get(blockId);
			if (!m_block.isCityExists(cityId)) {
				m_block.addCity(cityId);
			}
			// base
			City m_city = m_block.getCity(cityId);
			if (!m_city.isBaseExists(baseId)) {
				m_city.addBase(baseId);
			}
		}
		// 刷新所有城池状态
		getAllCity().forEach(p -> p.refreshStatus());
	}

	private void initEvent() {
		// 联盟事件
		AllianceEventDispatch.addListener(new IAllianceDisbandListener() {
			@Override
			public void onAllianceDisband(Alliance alliance, StateEnum state) {
				if (state == StateEnum.SUCCESS) {
					List<AllianceMember> m_Ams = AllianceMember.getByAid(alliance.getAid());
					List<Integer> uids = m_Ams.stream().map(p -> p.getUid()).collect(Collectors.toList());
					// 解散开始,先清理地图
					WorldMapService.resetWorldMapStateByUids(uids);
					WorldMapService.resetWorldMapCityState(alliance.getAid());
				}
			}
		});
		AllianceEventDispatch.addListener(new IAllianceMemberRemovedListener() {
			@Override
			public void onAllianceMemberRemoved(UserProfile source, UserProfile target, Alliance alliance,
					AllianceMember allianceMember, AllianceUserQuitCD allianceUserQuitCD, boolean isKicked) {
				WorldMapService.resetWorldMapStateByUid(target.getUid());
			}
		});
	}

	//////////////////////////////////////////////////////////
	public Base getBase(int blockId, int cityId, int baseId) {
		if (m_WorldMapData.containsKey(blockId)) {
			Block m_block = m_WorldMapData.get(blockId);
			if (m_block.isCityExists(cityId)) {
				City m_city = m_block.getCity(cityId);
				if (m_city.isBaseExists(baseId)) {
					return m_city.getBase(baseId);
				}
			}
		}
		return null;
	}

	public City getCity(int blockId, int cityId) {
		Block m_block = m_WorldMapData.get(blockId);
		if (m_block == null) {
			return null;
		}
		return m_block.getCity(cityId);
	}

	public Block getBlock(int blockId) {
		if (m_WorldMapData.containsKey(blockId)) {
			return m_WorldMapData.get(blockId);
		}
		return null;
	}

	public Collection<Block> getAllBlock() {
		return m_WorldMapData.values();
	}

	public Collection<City> getAllCity() {
		Collection<City> ret = new ArrayList<>();
		for (Block b : getAllBlock()) {
			ret.addAll(b.getAllCity());
		}
		return ret;
	}
	////////////////////////////////////////////////////////////

	public final Table getCacheCityTable() {
		return cacheCityTable;
	}

	public final Table getCacheBaseTable() {
		return cacheBaseTable;
	}

	public final Hash getCacheLastestBattleTable() {
		return cacheLastestBattleTable;
	}

	/////////////////////////////////////////////////////////////
	/**
	 * 获取当前联盟宣战城池个数
	 */
	public int getAllianceDeclarNum(String aid) {
		return (int) getAllCity().stream().filter(city -> city.getDeclarAid() == aid).count();
	}

	public boolean isAllianceDeclared(String aid) {
		return getAllianceDeclarNum(aid) > 0;
	}
}
